<?php

/**
 * Validator
 * 多种验证时，一旦碰到无效则停止验证，即判无效
 *
 * @package Validator
 * @author shukyyang@pplive.com
 * @version $Id: Validator.php 1279 2011-12-18 02:42:28Z shukyyang $
 */
namespace SF;

class Validator
{
    protected $_value;
    protected $_valid = true;
    protected $_message;
    protected $_invalid_skip = true;

    /**
     * 构造可传入value
     * @param mixed $value
     */
    public function __construct($value = null)
    {
        if (null !== $value) {
            $this->setValue($value);
        }
    }

    /**
     * 设置value
     * @param mixed $value
     */
    public function setValue($value)
    {
        $this->_value = $value;
    }

    /**
     * 返回验证后是否有效
     * @return bool
     */
    public function isValid()
    {
        return $this->_valid;
    }

    /**
     * 获取错误消息
     * @return string|array
     */
    public function getMessage()
    {
        return $this->_message;
    }

    /**
     * 进入集成式的验证处理
     * runValidator('isEmail')
     * runValidator(array('validator'=>'valueRange', 'options'=>array(1, 30)))
     * runvalidator(array(
     *     array('validator'=>'isEmail'),
     *     array('validator'=>'valueRange', 'options'=>array(1, 30), 'message'=>'xxxx')
     * ))
     * @param string|array $rule 如果为string时则为单个验证器
     * 数组形态时array('validator'=>'xxx', 'options'=>array(), 'message'=>'xxxx')
     * @return bool
     */
    public function runValidator($rule)
    {
        // 参数组织
        if (is_string($rule)) {
            $rule = array(array('validator' => $rule));
        } elseif (is_array($rule) && !empty($rule['validator'])) {
            $rule = array($rule);
        }
        // 聚合验证处理
        if (is_array($rule)) {
            foreach ($rule as $v) {
                if (!$this->_valid && $this->_invalid_skip) { // 设置为无效跳出验证
                    break;
                }
                if (empty($v['validator']) || !method_exists($this, $v['validator'])) {
                    require_once SF_PATH .'/Exception.php';
                    throw new \SF\Exception('无效的验证方法');
                }
                // 验证调用
                $options = array('value' => $this->_value);
                if (isset($v['options']) && is_array($v['options'])) {
                    $options = array_merge($options, $v['options']);
                }
                $this->_valid = call_user_func_array(array(__CLASS__, $v['validator']), $options);
                // 消息
                if (!$this->_valid) {
                    $message = (empty($v['message'])) ? '经验证无效' : $v['message'];
                    if ($this->_invalid_skip) {
                        $this->_message = $message;
                    } else {
                        $this->_message[$v['validator']] = $message;
                    }
                }
            }
        }
        return $this->_valid;
    }

    /**
     * 邮箱是否有效
     */
    public static function isEmail($value)
    {
        return preg_match('/^\w+([.]\w+)*[@]\w+([.]\w+)*[.][a-zA-Z]{2,4}$/', $value);
    }

    /**
     * 是否是日期
     * 格式：yyyy-mm-dd or yyyy/mm/dd
     */
    public static function isDate($value)
    {
        if (strpos($value, '-') !== false) {
            $p = '-';
        } elseif (strpos($value, '/') !== false) {
            $p = '\/';
        } else {
            return false;
        }
        if (preg_match('/^\d{4}' . $p . '\d{1,2}' . $p . '\d{1,2}$/', $value)) {
            $arr = explode($p, $value);
            if (count($arr) < 3)
                return false;
            list($year, $month, $day) = $arr;
            return checkdate($month, $day, $year);
        } else {
            return false;
        }
    }

    /**
     * 是否是Url
     * 可以不带http
     */
    public static function isUrl($value)
    {
        return preg_match('/[a-z0-9\.]+/i', $value);
    }

    /**
     * 自定义正则，是否匹配
     */
    public static function isMatch($value, $regxp)
    {
        return preg_match($regxp, $value);
    }

    /**
     * 值是否相等
     */
    public static function isEqual($value, $cmp)
    {
        return $value == $cmp && strlen($value) == strlen($cmp);
    }

    /**
     * 值是否完全同
     */
    public static function isSame($value, $cmp)
    {
        return $value === $cmp;
    }

    /**
     * 字串长度
     */
    public static function lengthRange($value, $min, $max)
    {
        $len = mb_strlen($value, 'UTF-8');
        return $len >= $min && $len <= $max;
    }

    /**
     * 值范围
     */
    public static function valueRange($value, $min, $max)
    {
        return $value >= $min && $value <= $max;
    }

    /**
     * 不为空
     */
    public static function notEmpty($value)
    {
        return !empty($value);
    }

    /**
     * 是否指定类型
     */
    public static function isType($value, $type)
    {
        return gettype($value) == $type;
    }

}